package com.examples.maps;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.graphics.Point;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;

import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter;
import com.google.android.gms.maps.GoogleMap.OnMapClickListener;
import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
import com.google.android.gms.maps.Projection;
import com.google.android.gms.maps.StreetViewPanorama;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polygon;
import com.google.android.gms.maps.model.PolygonOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;
import com.google.android.gms.maps.model.TileOverlayOptions;

public class MainActivity extends FragmentActivity implements MySupportMapFragment.MapCallback {

	private LocationManager locationManager;
	private MyLocation locationListener;
	private MySupportMapFragment mapFrag;
	private GoogleMap map;
	private Polyline polyline;
	private Polygon polygon;
	private StreetViewPanorama mSvp;
	private RadioGroup list_setting;
	private RadioButton btnHand, btnMarker, btnPolyline, btnPolygon;
	private Marker marker;
	private PolylineOptions polylOption;
	private PolygonOptions polygOption;
	private float zIndex = 1;
	private ArrayList<PolygonOptions> mPolygons;
	private dbShape dbShape;
	private MyShape mShape;

	private static final LatLng SYDNEY = new LatLng(-33.87365, 151.20689);

	
	public void tapEvent(int x, int y) {
		Log.d("TAG", String.format("tap event x=%d y=%d", x, y));		
		 
		Projection pp = map.getProjection(); 
		LatLng point = pp.fromScreenLocation(new Point(x,y));
		 mPolygons = dbShape.getPolygon();
			for(int i=0;i<mPolygons.size();i++){
				
			if(isPointInPolygon(point,mPolygons.get(i).getPoints())){
				
				marker = map.addMarker(new MarkerOptions().position(point).visible(false));
				map.setInfoWindowAdapter(new InfoWindowAdapter() {
					
					@Override
					public View getInfoWindow(Marker arg0) {
						// TODO Auto-generated method stub
						arg0.showInfoWindow();
						return null;
					}
					
					@Override
					public View getInfoContents(Marker arg0) {
						// TODO Auto-generated method stub
						return null;
					}
				});
			}
			}
			
		/*
		 * Projection pp = map.getProjection(); 
		 * LatLng point = pp.fromScreenLocation(new Point(x,y)); 
		 * for (Shape ss : mPolygons){
		 * if(ss.isPointInPolygon(point)){ ss.mMarkers.get(0).marker.s }
		 * 
		 * 
		 * }
		 */}

	@Override
	protected void onCreate(final Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		// mapFrag = ((MapFragment)
		// getFragmentManager().findFragmentById(R.id.map));
		// mapFrag.newInstance(new GoogleMapOptions().);

		try {
		mapFrag = (MySupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
		
		if(mapFrag==null){
			mapFrag = (MySupportMapFragment) MySupportMapFragment.newInstance();
			mapFrag.setMapCallback(this);
			FragmentTransaction fragmentTrans = getSupportFragmentManager().beginTransaction();
			fragmentTrans.add(R.id.map, mapFrag, "MAP_FRAGMENT_TAG");
			fragmentTrans.commit();
		}
		else {
			mapFrag.setMapCallback(this);
		}
		} catch (Exception e) {
            e.printStackTrace();
            Log.e("TAG", "Google Maps can't be loaded", e);
		}
		
		

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();
		switch (id) {
		case R.id.menu_map:
			map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
			break;
		case R.id.menu_satellite:
			map.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
			break;
		}
		return true;
	}

	private class MyLocation implements LocationListener {
		@Override
		public void onLocationChanged(Location location) {
			String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss")
					.format(new Date());
			double lat = (double) (location.getLatitude());
			double lng = (double) (location.getLongitude());
			float accur = (float) (location.getAccuracy());
			String loca = timeStamp + ":" + Double.toString(lat) + ","
					+ Double.toString(lng) + "-" + Float.toString(accur);
			Log.i("location", loca);
		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
			// TODO Auto-generated method stub

		}

		@Override
		public void onProviderEnabled(String provider) {
			Toast.makeText(getApplicationContext(),
					"Enabled new provider " + provider, Toast.LENGTH_SHORT)
					.show();

		}

		@Override
		public void onProviderDisabled(String provider) {
			Toast.makeText(getApplicationContext(),
					"Disabled provider " + provider, Toast.LENGTH_SHORT).show();
		}

	}

	public boolean isEnableNetwork() {
		Context context = getApplicationContext();
		if (context == null)
			return true;
		ConnectivityManager conMgr = (ConnectivityManager) context
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		return conMgr.getActiveNetworkInfo() != null
				&& conMgr.getActiveNetworkInfo().isAvailable()
				&& conMgr.getActiveNetworkInfo().isConnected();
	}

	private void setUpMap() {
		map.setMapType(GoogleMap.MAP_TYPE_NONE);

		map.addTileOverlay(new TileOverlayOptions().tileProvider(new CustomMapTileProvider(getResources()
						.getAssets())).zIndex(0f));
		map.setMyLocationEnabled(true);

		CameraUpdate upd = CameraUpdateFactory.newLatLngZoom(new LatLng(
				10.782810, 106.696035), 18);
		map.moveCamera(upd);
	}

	public class clickEvent implements OnMapClickListener{

		@Override
		public void onMapClick(LatLng loca) {
			// TODO Auto-generated method stub
			mPolygons = dbShape.getPolygon();
			for(int i=0;i<mPolygons.size();i++){
				marker = map.addMarker(new MarkerOptions().position(loca));
			if(mShape.isPointInPolygon(loca,mPolygons.get(i).getPoints())){
				
			}
			}
		}
		
	}
	public class insertMarker implements OnMapClickListener {

		@Override
		public void onMapClick(LatLng loca) {
			// TODO Auto-generated method stub
			MarkerOptions makerO = makeMarker(loca);
			if (makerO.isVisible()) {
				Marker mark = map.addMarker(makerO);
				MyShape shape = new MyShape();
				shape.setName(mark.getTitle());
				shape.setType("marker");
				shape.setPoint(mark.getPosition().toString());
				dbShape.insertShape(shape);

				map.moveCamera(CameraUpdateFactory.newLatLngZoom(loca, 18));
			}

		}

	}

	public MarkerOptions makeMarker(LatLng loca) {
		MarkerOptions markOption = new MarkerOptions();
		markOption.position(loca);
		// markOption.icon(BitmapDescriptorFactory.fromResource(R.drawable.mark));
		markOption.draggable(true);
		markOption.icon(BitmapDescriptorFactory
				.defaultMarker(BitmapDescriptorFactory.HUE_BLUE));

		markOption.title(getName());
		return markOption;
	}

	public class insertPolyline implements OnMapClickListener {

		@Override
		public void onMapClick(LatLng loca) {
			// TODO Auto-generated method stub

			Marker marke = map
					.addMarker(new MarkerOptions().position(loca).icon(
							BitmapDescriptorFactory
									.fromResource(R.drawable.mark)));

			polylOption.add(loca);
			polylOption.color(Color.MAGENTA);
			polyline = map.addPolyline(polylOption);

		}

	}

	public class newPolyline implements OnMapLongClickListener {

		@Override
		public void onMapLongClick(LatLng loca) {
			// TODO Auto-generated method stub
			Marker marke = map
					.addMarker(new MarkerOptions().position(loca).icon(
							BitmapDescriptorFactory
									.fromResource(R.drawable.mark)));
			polylOption.add(loca);
			polyline = map.addPolyline(polylOption);
			final MyShape shape = new MyShape();

			final AlertDialog.Builder alert = new AlertDialog.Builder(
					getApplicationContext());
			final EditText input = new EditText(getApplicationContext());
			alert.setView(input);
			alert.setTitle("Name");
			alert.setPositiveButton("OK",
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog,
								int whichButton) {
							String value = input.getText().toString().trim();
							shape.setName(value);
						}
					});
			shape.setType("polyline");
			polyline.getPoints();
			dbShape.insertShape(shape);

			polylOption = new PolylineOptions();
			polylOption.zIndex(zIndex);

			zIndex = zIndex + 1;
			map.setOnMapClickListener(new insertPolyline());
		}

	}

	public class insertPolygon implements OnMapClickListener {
		@Override
		public void onMapClick(LatLng loca) {
			// TODO Auto-generated method stub

			Marker marke = map
					.addMarker(new MarkerOptions().position(loca).icon(
							BitmapDescriptorFactory
									.fromResource(R.drawable.mark)));

			polylOption.add(loca);
			polylOption.color(Color.MAGENTA);
			polyline = map.addPolyline(polylOption);
		}
	}

	public class newPolygon implements OnMapLongClickListener {

		@Override
		public void onMapLongClick(LatLng loca) {
			// TODO Auto-generated method stub
			Marker marke = map
					.addMarker(new MarkerOptions().position(loca).icon(
							BitmapDescriptorFactory
									.fromResource(R.drawable.mark)));

			polylOption.add(loca);
			polygOption.addAll(polylOption.getPoints());
			polygOption.strokeColor(Color.MAGENTA);
			polygOption.fillColor(0x7F00FF00);
			polygOption.zIndex(polylOption.getZIndex());

			polyline.remove();
			polygon = map.addPolygon(polygOption);

			MyShape shape = new MyShape();
			shape.setName(getName());
			shape.setType("polygon");
			String point = new String();
			List<LatLng> listLoca = polygon.getPoints();
			for (int i = 0; i < listLoca.size(); i++) {
				point += (Double.toString(listLoca.get(i).latitude)) + ","
						+ (Double.toString(listLoca.get(i).longitude)) + ";";
			}
			point = point.substring(0, point.length()-1);
			shape.setPoint(point);
			dbShape.insertShape(shape);
			polygOption = new PolygonOptions();
			polylOption = new PolylineOptions();
			polylOption.zIndex(zIndex);
			zIndex = zIndex + 1;
			map.setOnMapClickListener(new insertPolygon());
		}

	}

	public String getName(){
		
		final AlertDialog.Builder alert = new AlertDialog.Builder(this);
		final EditText input = new EditText(this);
		alert.setView(input);
		alert.setTitle("Name");
		alert.setPositiveButton("OK",
				new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog,
							int whichButton) {						
						
					}
				});
		alert.show();
		String value1 = input.getText().toString().trim();
		return value1;
	}	

	@Override
	public void onMapReady(final GoogleMap map) {
		// TODO Auto-generated method stub		

		this.map = map;
		map.setMyLocationEnabled(true);
		dbShape = new dbShape(getApplicationContext());
		locationListener = new MyLocation();		

		list_setting = (RadioGroup) findViewById(R.id.radio_group_list_selector);

		btnHand = (RadioButton) findViewById(R.id.ibtnHand);
/*
		btnHand.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(CompoundButton buttonView,
					boolean isChecked) {
				// TODO Auto-generated method stub
				if (isChecked) {
					map.setOnMapClickListener(new clickEvent());
				} else
					return;
			}
		});
*/
		btnMarker = (RadioButton) findViewById(R.id.ibtnMarker);
		btnMarker.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(CompoundButton buttonView,
					boolean isChecked) {
				// TODO Auto-generated method stub
				if (isChecked) {
					map.setOnMapClickListener(new insertMarker());
				} else
					return;
			}
		});

		btnPolyline = (RadioButton) findViewById(R.id.ibtnPolyline);
		btnPolyline.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(CompoundButton buttonView,
					boolean isChecked) {
				// TODO Auto-generated method stub
				if (isChecked) {
					polylOption = new PolylineOptions();
					polylOption.zIndex(zIndex);
					zIndex = zIndex + 1;
					map.setOnMapClickListener(new insertPolyline());
					map.setOnMapLongClickListener(new newPolyline());
				} else
					return;

			}

		});

		btnPolygon = (RadioButton) findViewById(R.id.ibtnPolygon);
		btnPolygon.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(CompoundButton buttonView,
					boolean isChecked) {
				// TODO Auto-generated method stub
				if (isChecked) {
					polylOption = new PolylineOptions();
					polygOption = new PolygonOptions();
					polylOption.zIndex(zIndex);
					zIndex = zIndex + 1;
					map.setOnMapClickListener(new insertPolygon());
					map.setOnMapLongClickListener(new newPolygon());
				} else
					return;

			}

		});

		// Get a handle to the Map Fragment
		if (isEnableNetwork()) {
			map.setMapType(GoogleMap.MAP_TYPE_NORMAL);

			LatLng sydney = new LatLng(-33.867, 151.206);

			map.setMyLocationEnabled(true);
			map.moveCamera(CameraUpdateFactory.newLatLngZoom(SYDNEY, 18));

			map.addMarker(new MarkerOptions().title("Sydney")
					.snippet("The most populous city in Australia.")
					.position(SYDNEY));
//			map.addPolygon(mPolygons.get(0).zIndex(10f));
			
			PolygonOptions rectOptions = new PolygonOptions()
					.add(new LatLng(37.35, -122.0), new LatLng(37.45, -122.0),
							new LatLng(37.45, -122.2),
							new LatLng(37.35, -122.2),
							new LatLng(37.35, -122.0)).strokeColor(Color.GREEN)
					.fillColor(Color.YELLOW).strokeWidth(5f);

			// Get back the mutable Polygon
			Polygon polygon = map.addPolygon(rectOptions);

		} else {
			setUpMap();

			// map.addMarker(new MarkerOptions().icon(icon));
			map.addMarker(new MarkerOptions()
					.title("Sydney")
					.snippet("The most populous city in Australia.")
					.position(new LatLng(10.782810, 106.696035))
					.icon(BitmapDescriptorFactory
							.fromResource(R.drawable.mark)));

			polyline = map.addPolyline(new PolylineOptions()
					.add(new LatLng(10.782810, 106.696035),
							new LatLng(10.78003354, 106.6842307),
							new LatLng(10.783788031, 106.69700861))
					.color(Color.MAGENTA).zIndex(1000));
		}
		
		mPolygons = dbShape.getPolygon();
		for (int i = 0; i < mPolygons.size(); i++) {
			PolygonOptions gonOp = mPolygons.get(i);
			polygon = map.addPolygon(gonOp);
		}

	}
	
	public boolean isPointInPolygon(LatLng tap, List<LatLng> vertices) {
		int intersectCount = 0;
		for (int j = 0; j < vertices.size() - 1; j++) {
			if (rayCastIntersect(tap, vertices.get(j), vertices.get(j + 1))) {
				intersectCount++;
			}
		}

		return (intersectCount % 2) == 1; // odd = inside, even = outside;
	}

	private boolean rayCastIntersect(LatLng tap, LatLng vertA, LatLng vertB) {

		double aY = vertA.latitude;
		double bY = vertB.latitude;
		double aX = vertA.longitude;
		double bX = vertB.longitude;
		double pY = tap.latitude;
		double pX = tap.longitude;

		if ((aY > pY && bY > pY) || (aY < pY && bY < pY)
				|| (aX < pX && bX < pX)) {
			return false; // a and b can't both be above or below pt.y, and a or
							// b must be east of pt.x
		}

		double m = (aY - bY) / (aX - bX); // Rise over run
		double bee = (-aX) * m + aY; // y = mx + b
		double x = (pY - bee) / m; // algebra is neat!

		return x > pX;
	}
}
